/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.pictavore.gui

import org.jdesktop.application.FrameView
import org.jdesktop.application.SingleFrameApplication

import com.google.inject.Inject

import com.pictavore.plugin.tool.ToolPluginManager
import com.pictavore.plugin.tool.ToolPlugin
import org.jdesktop.application.TaskMonitor
import org.jdesktop.application.ResourceMap
import java.beans.PropertyChangeEvent
import java.awt.event.ActionEvent
import javax.swing.Action
import javax.swing.JFrame
import javax.swing.JSlider
import javax.swing.JDialog
import javax.swing.Icon
import javax.swing.ListSelectionModel
import java.awt.event.ActionListener
import java.beans.PropertyChangeListener
import net.miginfocom.swing.MigLayout

import groovy.swing.SwingBuilder
import java.awt.Graphics
import javax.swing.JPanel
import java.awt.BorderLayout
import javax.swing.event.ListSelectionListener

/**
 *
 * @author caleb
 */
class ImageView extends FrameView {
    @Inject
    private ToolPluginManager toolPluginManager;
    public List<ToolPlugin> getToolPlugins() { return (List<ToolPlugin>) toolPluginManager.toolPlugins; }

    // Variables declaration - do not modify
    private javax.swing.JPanel mainPanel;
    private javax.swing.JMenuBar menuBar;
    private javax.swing.JProgressBar progressBar;
    private javax.swing.JLabel statusAnimationLabel;
    private javax.swing.JLabel statusMessageLabel;
    private javax.swing.JPanel statusPanel;
    private javax.swing.JTable toolPlugins;
    // End of variables declaration

    private final javax.swing.Timer messageTimer;
    private final javax.swing.Timer busyIconTimer;
    private final Icon idleIcon;
    private final Icon[] busyIcons = new Icon[15];
    private int busyIconIndex = 0;

    @Inject
    private final DisplayPanel displayPanel;

    private JDialog aboutBox;

    @Inject
    def ImageView(SingleFrameApplication app) {
        super(app);
    }

    def init() {
        initComponents();

        // status bar initialization - message timeout, idle icon and busy animation, etc
        ResourceMap resourceMap = getResourceMap();

        // Blank the status message after a time
        int messageTimeout = resourceMap.getInteger("StatusBar.messageTimeout");
        messageTimer = new javax.swing.Timer(messageTimeout, { ActionEvent e ->
            statusMessageLabel.setText("");
        } as ActionListener)

        messageTimer.setRepeats(false);

        // Animate the busy icon
        int busyAnimationRate = resourceMap.getInteger("StatusBar.busyAnimationRate");
        busyIcons.eachWithIndex { o, i ->
            busyIcons[i] = resourceMap.getIcon("StatusBar.busyIcons[${i}]");
        }

        busyIconTimer = new javax.swing.Timer(busyAnimationRate, { ActionEvent e ->
            busyIconIndex = (busyIconIndex + 1) % busyIcons.length;
            statusAnimationLabel.setIcon(busyIcons[busyIconIndex]);
        } as ActionListener)

        idleIcon = resourceMap.getIcon("StatusBar.idleIcon");
        statusAnimationLabel.setIcon(idleIcon);
        progressBar.setVisible(false);

        // connecting action tasks to status bar via TaskMonitor
        TaskMonitor taskMonitor = new TaskMonitor(this.application.context);
        taskMonitor.addPropertyChangeListener( { PropertyChangeEvent evt ->
                String propertyName = evt.propertyName;
                if ("started".equals(propertyName)) {
                    if (!busyIconTimer.isRunning()) {
                        statusAnimationLabel.setIcon(busyIcons[0]);
                        busyIconIndex = 0;
                        busyIconTimer.start();
                    }
                    progressBar.setVisible(true);
                    progressBar.setIndeterminate(true);
                } else if ("done".equals(propertyName)) {
                    busyIconTimer.stop();
                    statusAnimationLabel.setIcon(idleIcon);
                    progressBar.setVisible(false);
                    progressBar.setValue(0);
                } else if ("message".equals(propertyName)) {
                    String text = (String)(evt.getNewValue());
                    statusMessageLabel.setText((text == null) ? "" : text);
                    messageTimer.restart();
                } else if ("progress".equals(propertyName)) {
                    int value = (Integer)(evt.getNewValue());
                    progressBar.setVisible(true);
                    progressBar.setIndeterminate(false);
                    progressBar.setValue(value);
                }
            } as PropertyChangeListener);
    }

    @Action
    public void showAboutBox() {
//        if (aboutBox == null) {
//            JFrame mainFrame = PictavoreApp.getApplication().getMainFrame();
//            aboutBox = new PictavoreAboutBox(mainFrame);
//            aboutBox.setLocationRelativeTo(mainFrame);
//        }
//        PictavoreApp.getApplication().show(aboutBox);
    }

    private initComponents() {
        def swing = new SwingBuilder()
        def layout = new MigLayout("fill", // Layout
                                   "0[pref!][fill,grow][550]0", // Column
                                   "0[fill][pref!]0") // Row

        def toolPanelCards = swing.panel() { cardLayout() }
        def toolPanel = swing.panel() {
            borderLayout();
            widget(toolPanelCards, constraints: BorderLayout.CENTER)
        }

        this.getToolPlugins().each { p ->
            toolPanelCards.add(p.component, p.displayName)
        }

        def selectionModel

        mainPanel = swing.panel(layout:layout, background: java.awt.Color.BLUE) {
            slider(constraints: "growy", orientation: JSlider.VERTICAL)
            panel(constraints: "grow", background: java.awt.Color.PINK) {
                borderLayout()
                widget(this.displayPanel, constraints: BorderLayout.CENTER)
            }

            panel(constraints: "grow, wrap, spany", layout: new MigLayout("fill", "0[fill]0", "0[grow][240]0")) {
                splitPane(constraints: "grow, wrap") {
                    scrollPane(preferredSize: [150, -1], minimumSize: [150, -1]) {
                        table() {
                            selectionModel = current.selectionModel
                            current.selectionModel.selectionMode = ListSelectionModel.SINGLE_SELECTION
                            current.selectionModel.addListSelectionListener( { e ->
                                if (! e.valueIsAdjusting) {
                                    for (int i = e.source.minSelectionIndex; i <= e.source.maxSelectionIndex; ++i) {
                                        if (e.source.isSelectedIndex(i)) {
                                            (toolPanelCards.layout).show(toolPanelCards, toolPlugins[i].displayName)
                                            break
                                        }
                                    }
                                    toolPanelCards.revalidate()
                                }
                            } as ListSelectionListener)

                            tableModel(list: toolPlugins) {
                                propertyColumn(header: "Tool", propertyName: "displayName")
    //                            closureColumn(header: "Quadrat", read: { it.square })
                            }
                        }
                    }
                    widget(toolPanel, constraints: "grow, w 280:280:")
                }
                panel(background: java.awt.Color.YELLOW, constraints: "grow") {
                    borderLayout()
                    slider(constraints: BorderLayout.WEST, orientation: JSlider.VERTICAL)
                }
            }

            panel(background: java.awt.Color.BLACK, constraints: "spanx, growx, h 140!")
        }

        // select the first tool
        selectionModel.setSelectionInterval(0, 0)

        menuBar = new javax.swing.JMenuBar();
        javax.swing.JMenu fileMenu = new javax.swing.JMenu();
        javax.swing.JMenuItem exitMenuItem = new javax.swing.JMenuItem();
        javax.swing.JMenu helpMenu = new javax.swing.JMenu();
        javax.swing.JMenuItem aboutMenuItem = new javax.swing.JMenuItem();
        statusPanel = new javax.swing.JPanel();
        javax.swing.JSeparator statusPanelSeparator = new javax.swing.JSeparator();
        statusMessageLabel = new javax.swing.JLabel();
        statusAnimationLabel = new javax.swing.JLabel();
        progressBar = new javax.swing.JProgressBar();

        mainPanel.setName("mainPanel"); // NOI18N


        menuBar.setName("menuBar"); // NOI18N

        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(com.pictavore.PictavoreApp).getContext().getResourceMap(ImageView);
        fileMenu.setText(resourceMap.getString("fileMenu.text")); // NOI18N
        fileMenu.setName("fileMenu"); // NOI18N

        javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(com.pictavore.PictavoreApp).getContext().getActionMap(ImageView, this);
        exitMenuItem.setAction(actionMap.get("quit")); // NOI18N
        exitMenuItem.setName("exitMenuItem"); // NOI18N
        fileMenu.add(exitMenuItem);

        menuBar.add(fileMenu);

        helpMenu.setText(resourceMap.getString("helpMenu.text")); // NOI18N
        helpMenu.setName("helpMenu"); // NOI18N

        aboutMenuItem.setAction(actionMap.get("showAboutBox")); // NOI18N
        aboutMenuItem.setName("aboutMenuItem"); // NOI18N
        helpMenu.add(aboutMenuItem);

        menuBar.add(helpMenu);

        statusPanel.setName("statusPanel"); // NOI18N

        statusPanelSeparator.setName("statusPanelSeparator"); // NOI18N

        statusMessageLabel.setName("statusMessageLabel"); // NOI18N

        statusAnimationLabel.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        statusAnimationLabel.setName("statusAnimationLabel"); // NOI18N

        progressBar.setName("progressBar"); // NOI18N

        org.jdesktop.layout.GroupLayout statusPanelLayout = new org.jdesktop.layout.GroupLayout(statusPanel);
        statusPanel.setLayout(statusPanelLayout);
        statusPanelLayout.setHorizontalGroup(
            statusPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(statusPanelSeparator, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
            .add(statusPanelLayout.createSequentialGroup()
                .addContainerGap()
                .add(statusMessageLabel)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 226, Short.MAX_VALUE)
                .add(progressBar, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(statusAnimationLabel)
                .addContainerGap())
        );
        statusPanelLayout.setVerticalGroup(
            statusPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(statusPanelLayout.createSequentialGroup()
                .add(statusPanelSeparator, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .add(statusPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(statusMessageLabel)
                    .add(statusAnimationLabel)
                    .add(progressBar, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                .add(3, 3, 3))
        );

        setComponent(mainPanel);
        setMenuBar(menuBar);
        setStatusBar(statusPanel);
    }
}
